package jard.webshop.nbp;

import jard.webshop.util.Constants;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapKeyJoinColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;

/**
 *
 * @author cjp
 */
@Entity(name = "Order_unit")
@NamedQueries(
@NamedQuery(name = Constants.GET_ALL_ORDERS, query = "SELECT o FROM Order_unit o"))
public class Order implements Serializable {

    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long trackingNumber;
    
    @Column(nullable = false)
    @ElementCollection
    @MapKeyJoinColumn(name = "name")
    private Map<Product, Integer> products = new HashMap<Product, Integer>();
    
    @OneToOne(cascade=CascadeType.ALL)
    private Invoice invoice;
    
    @Column(nullable = false)
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date orderDate = Calendar.getInstance().getTime();
    
    private Boolean shipped = false;
    // If we want to give customers the option to buy things not yet in stock
    // this would have to be OneToMany
    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    private Shipment shipment;
    
    @ManyToOne
    @JoinColumn(nullable=false)
    private User user;

    public Order() {
    }
    
    public Order(User user) {
        this.user = user;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (trackingNumber != null ? trackingNumber.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Order)) {
            return false;
        }
        Order other = (Order) object;
        if ((this.trackingNumber == null && other.trackingNumber != null)
                || (this.trackingNumber != null
                && !this.trackingNumber.equals(other.trackingNumber))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "jard.webshop.nbp.Order[ id=" + trackingNumber + " ]";
    }
    /* Commenting out before complete removal, in case it breaks something
    public Long getId() {
        return trackingNumber;
    }

    public void setId(Long id) {
        this.trackingNumber = id;
    }*/

    public Long getTrackingNumber() {
        return trackingNumber;//trackingNumber;
    }

    public void setTrackingNumber(Long trackingNumber) {
        this.trackingNumber = trackingNumber;
    }

    // MUST PERSIST Products BEFORE ADDING HERE
    public void addProduct(Product p, Integer quantity) {
        products.put(p, quantity);
    }

    public Map<Product, Integer> getProducts() {
        return products;
    }

    public void setProducts(Map<Product, Integer> products) {
        this.products = products;
    }

    public Date getOrderDate() {
        return orderDate;
    }

    public void setOrderDate(Date orderDate) {
        this.orderDate = orderDate;
    }

    public Boolean isShipped() {
        return shipped;
    }

    public void setShipped(Boolean shipped) {
        this.shipped = shipped;
    }

    public Shipment getShipment() {
        return shipment;
    }

    public void setShipment(Shipment shipment) {
        this.shipment = shipment;
    }

    public Invoice getInvoice() {
        return invoice;
    }

    public void setInvoice(Invoice invoice) {
        this.invoice = invoice;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
    
    // Law of Demeter, or whatever it's called
    public Boolean isPaid() {
        if(invoice != null) {
            return invoice.isPaid();
        } else {
            return false;
        }
    }
}
